package com.ailiwu.www.ailiwu.zxing.encoding;

import android.graphics.Bitmap;
import android.graphics.Matrix;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;

import java.util.Hashtable;

/**
 * @author Ryan Tang
 *
 */
public final class EncodingHandler {
	private static final int BLACK = 0xff000000;
	
	/*
	 * 生成二维码图片的处理思路：
	 * 先按照指定的宽高要求创建一个空白Bitmap
	 * 将这个Bitmap对应的范围内平均切分成n个像素块
	 * 通过方式去计算当前的每个像素点上应该显示的数据
	 * 将所有的像素点上应该显示的数据计算完成后，拼接起来即可的到对应的二维码的图片
	 * */
	public static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException {
		Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
       //设置稍后将文字转为数字解析时的字符编码
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		
		/*
		 * 通过encode方法直接将文字转化成对应二维码图形块
		 * 方法中的参数：
		 * 1. 要解析的字符串
		 * 2. 要将字符串解析成何种编码，即二维码还是条形码
		 * 3，4. 生成的图形块的宽高
		 * */
		BitMatrix matrix = new MultiFormatWriter().encode(str,
				BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
		//获取图形块对应的宽高
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		//根据图形块的宽高生成对应长度的像素数据的数组
		int[] pixels = new int[width * height];
		
		//根据宽高的值，进行双层的for循环，目的是在这个循环中给数组的每一个位置赋值
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				//根据get方法进行判断，判断当前x,y位置上是应该显示颜色还是不应该显示颜色
				if (matrix.get(x, y)) {
					pixels[y * width + x] = BLACK;
					
					//思考：假设将宽度一分为二，让左边显示红色，右边显示蓝色
//					if(x < (width /2)) {
//						pixels[y * width + x] = 0xffff0000;
//					} else {
//						pixels[y * width + x] = 0xff0000ff;
//					}
				} 
			}
		}
		
		Bitmap bitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		//将计算好的像素数组中的值设置到bitmap上进行显示
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}
	
	
	//自定义方法，用于生成中间带图片的二维码
	//注意：中心图形不能太大
	//参数三代表中心的图片
	public static Bitmap createQRCode(String str,int widthAndHeight,Bitmap centerBit) throws WriterException {
		//先将中心图片缩小，缩小成二维码图形块的1/8
		Matrix m = new Matrix();
		float sx = (widthAndHeight/8) / (float)centerBit.getWidth();
		float sy = (widthAndHeight/8) /  (float)centerBit.getHeight();
		m.setScale(sx, sy);
		Bitmap bitm = Bitmap.createBitmap(centerBit, 0, 0, centerBit.getWidth(), centerBit.getHeight(), m, true);
		
		Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
       //设置稍后将文字转为数字解析时的字符编码
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		
		/*
		 * 通过encode方法直接将文字转化成对应二维码图形块
		 * 方法中的参数：
		 * 1. 要解析的字符串
		 * 2. 要将字符串解析成何种编码，即二维码还是条形码
		 * 3，4. 生成的图形块的宽高
		 * */
		BitMatrix matrix = new MultiFormatWriter().encode(str,
				BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
		//获取图形块对应的宽高
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		//根据图形块的宽高生成对应长度的像素数据的数组
		int[] pixels = new int[width * height];
		
		int w = width / 2;
		int h = height / 2;
		int bw = bitm.getWidth() /2;
		int bh = bitm.getHeight() /2;
		//根据宽高的值，进行双层的for循环，目的是在这个循环中给数组的每一个位置赋值
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				//根据get方法进行判断，判断当前x,y位置上是应该显示颜色还是不应该显示颜色
				if (x > (w - bw) && x < (w+bw) 
						&& y > (h-bh) && y < (h+bh)){
					//判断当前像素点的位置是否应该显示图片
					//应该显示图片，那么就让该点的值为图片的值
					pixels[y * width + x] =  bitm.getPixel(x - (w-bw), y-(h-bh));
				} else {
					if (matrix.get(x, y)) {
						pixels[y * width + x] = BLACK;
					} 
				}
			}
		}
		
		Bitmap bitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		//将计算好的像素数组中的值设置到bitmap上进行显示
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}
}
